home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9203.ZIP / 386BSD.392 next >
Text File  |  1992-01-24  |  8KB  |  237 lines

  1. _PORTING UNIX TO THE 386: DEVICE DRIVERS_
  2. by William Jolitz and Lynne Jolitz
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /* [Excerpted from /sys/i386/isa/icu.h] */
  8.  ...
  9. /* Interrupt enable bits -- in order of priority */
  10. #define IRQ0        0x0001      /* highest priority - timer */
  11. #define IRQ1        0x0002
  12. #define IRQ_SLAVE   0x0004
  13. #define IRQ8        0x0100
  14. #define IRQ9        0x0200
  15. #define IRQ2        IRQ9
  16. #define IRQ10       0x0400
  17. #define IRQ11       0x0800
  18. #define IRQ12       0x1000
  19. #define IRQ13       0x2000
  20. #define IRQ14       0x4000
  21. #define IRQ15       0x8000
  22. #define IRQ3        0x0008
  23. #define IRQ4        0x0010
  24. #define IRQ5        0x0020
  25. #define IRQ6        0x0040
  26. #define IRQ7        0x0080      /* lowest - parallel printer */
  27.  ...
  28.  
  29.  
  30.  
  31.  
  32. [LISTING TWO]
  33.  
  34. /* [Excerpted from /sys/i386/isa/icu.h] */
  35.   ...
  36. /* Interrupt "level" mechanism variables, masks, and macros */
  37.  
  38. #define INTREN(s)   __nonemask__ &= ~(s)
  39. #define INTRDIS(s)  __nonemask__ |= (s)
  40. #define INTRMASK(msk,s) msk |= (s)
  41.   ...
  42. /* [Excerpted from /sys/i386/isa/isa.c] */
  43.   ...
  44. /* Configure all ISA devices */
  45. isa_configure() {
  46.     struct isa_device *dvp;
  47.     struct isa_driver *dp;
  48.     splhigh();
  49.     INTREN(IRQ_SLAVE);
  50.     /* configure devices, constructing group masks as we go */
  51.     for (dvp = isa_devtab_bio; config_isadev(dvp,&__biomask__); dvp++);
  52.     for (dvp = isa_devtab_tty; config_isadev(dvp,&__ttymask__); dvp++);
  53.     for (dvp = isa_devtab_net; config_isadev(dvp,&__netmask__); dvp++);
  54.     for (dvp = isa_devtab_null; config_isadev(dvp,0); dvp++);
  55. /* if we support slip, then any tty interrupt is a potential net intr */
  56. #include "sl.h"
  57. #if NSL > 0
  58.     __netmask__ |= __ttymask__;
  59.     __ttymask__ |= __netmask__;
  60. #endif
  61.  
  62.     /* if not enabled, don't allow in ANY mask to become enabled */
  63.     __biomask__ |= __nonemask__;
  64.     __ttymask__ |= __nonemask__;
  65.     __netmask__ |= __nonemask__;
  66.     __protomask__ |= __nonemask__;
  67.     splnone();
  68. }
  69. /* Configure an ISA device. */
  70. config_isadev(isdp, mp)
  71.     struct isa_device *isdp;
  72.     int *mp;
  73. {
  74.     struct isa_driver *dp;
  75.     if (dp = isdp->id_driver) {
  76.         /* does this device have any I/O shared memory? */
  77.         if (isdp->id_maddr) {
  78.             extern int atdevbase[];
  79.             /* convert from PC absolute physical to virtual */
  80.             isdp->id_maddr -= IOM_BEGIN;
  81.             isdp->id_maddr += (int)&atdevbase;
  82.         }
  83.         /* "Is there anyone on board?" -- Star Trek */
  84.         isdp->id_alive = (*dp->probe)(isdp);
  85.         if (isdp->id_alive) {
  86.             printf("%s%d", dp->name, isdp->id_unit);
  87.             (*dp->attach)(isdp);
  88.             printf(" at 0x%x ", isdp->id_iobase);
  89.             /* have we got an interrupt to wire down? */
  90.             if(isdp->id_irq) {
  91.                 int intrno;
  92.                 intrno = ffs(isdp->id_irq)-1;
  93.                 printf("irq %d ", intrno);
  94.                 INTREN(isdp->id_irq);
  95.                 /* add to a group mask?? */
  96.                 if(mp)INTRMASK(*mp,isdp->id_irq);
  97.                 /* wire interrupt */
  98.                 setidt(ICU_OFFSET+intrno, isdp->id_intr,
  99.                      SDT_SYS386IGT, SEL_KPL);
  100.             }
  101.             /* perhaps a DMA channel request as well? */
  102.                        if (isdp->id_drq != -1) printf("drq %d ", isdp->id_drq);
  103.  
  104.             printf("on isa\n");
  105.         }
  106.         return (1);
  107.     } else  return(0);
  108. }
  109. ...
  110.  
  111.  
  112.  
  113.  
  114. [LISTING THREE
  115.  
  116. /* [Excerpted from /sys/i386/include/param.h] */
  117.  
  118.   ...
  119. #ifndef __ORPL__
  120. /* Interrupt Group Masks  */
  121. extern  u_short __highmask__;   /* interrupts masked with splhigh() */
  122. extern  u_short __ttymask__;    /* interrupts masked with spltty() */
  123. extern  u_short __biomask__;    /* interrupts masked with splbio() */
  124. extern  u_short __netmask__;    /* interrupts masked with splimp() */
  125. extern  u_short __protomask__;  /* interrupts masked with splnet() */
  126. extern  u_short __nonemask__;   /* interrupts masked with splnone() */
  127.  
  128. asm("   .set IO_ICU1, 0x20 ; .set IO_ICU2, 0xa0 "); 
  129.  
  130. /* adjust priority level to disable a group of interrupts */
  131. #define __ORPL__(m) ({ u_short oldpl, msk; \
  132.     msk = (msk); \
  133.     asm volatile (" \
  134.     cli ;               /* modify interrupts atomically */ \
  135.     movw    %1, %%dx ;      /* get mask to OR in */ \
  136.     inb $ IO_ICU1+1, %%al ; /* get low order mask */ \
  137.     xchgb   %%dl, %%al ;        /* switch the old with the new */ \
  138.     orb %%dl, %%al ;        /* finally, OR both it in! */ \
  139.     outb    %%al, $ IO_ICU1+1 ;     /* and stuff it back where it came */ \
  140.     inb $ 0x84, %%al ;      /* post it & handle write recovery */ \
  141.     inb $ IO_ICU2+1, %%al ; /* next, get high order mask */ \
  142.     xchgb   %%dh, %%al ;        /* switch the old with the new */ \
  143.     orb %%dh, %%al ;        /* finally, or it in! */ \
  144.     outb    %%al, $ IO_ICU2+1 ;     /* and stuff it back where it came */ \
  145.     inb $ 0x84, %%al ;      /* post it & handle write recovery */ \
  146.     movw    %%dx, %0 ;      /* return old mask */ \
  147.     sti             /* allow interrupts again */ " \
  148.     : "&=g" (oldpl)         /* return values */ \
  149.     : "g" ((m))         /* arguments */ \
  150.     : "ax", "dx"            /* registers used */ \
  151.     ); \
  152.     oldpl;              /* return the "old" value */ \
  153. })
  154. /* force priority mask to a set value */
  155. #define __SETPL__(m)    ({ u_short oldpl, msk; \
  156.     msk = (msk); \
  157.     asm volatile (" \
  158.     cli ;               /* modify interrupts atomically */ \
  159.     movw    %1, %%dx ;      /* get mask to OR in */ \
  160.     inb $ IO_ICU1+1, %%al ; /* get low order mask */ \
  161.     xchgb   %%dl, %%al ;        /* switch the old with the new */ \
  162.     outb    %%al, $ IO_ICU1+1 ;     /* and stuff it back where it came */ \
  163.     inb $ 0x84, %%al ;      /* post it & handle write recovery */ \
  164.     inb $ IO_ICU2+1, %%al ; /* next, get high order mask */ \
  165.     xchgb   %%dh, %%al ;        /* switch the old with the new */ \
  166.     outb    %%al, $ IO_ICU2+1 ;     /* and stuff it back where it came */ \
  167.     inb $ 0x84, %%al ;      /* post it & handle write recovery */ \
  168.     movw    %%dx, %0 ;      /* return old mask */ \
  169.     sti             /* allow interrupts again */ " \
  170.     : "&=g" (oldpl)         /* return values */ \
  171.     : "g" ((m))         /* arguments */ \
  172.     : "ax", "dx"            /* registers used */ \
  173.     ); \
  174.     oldpl;              /* return the "old" value */ \
  175. })
  176. #define splhigh()   __ORPL__(__highmask__)
  177. #define spltty()    __ORPL__(__ttymask__)
  178. #define splbio()    __ORPL__(__biomask__)
  179. #define splimp()    __ORPL__(__netmask__)
  180. #define splnet()    __ORPL__(__protomask__)
  181. #define splsoftclock()  __ORPL__(__protomask__)
  182. #define splx(v) ({ u_short val; \
  183.     val = (v); \
  184.     if (val == __nonemask__) (void) spl0(); /* zero is special */ \
  185.     else (void) __SETPL__(val); \
  186. })
  187. #endif __ORPL__
  188.  ...
  189.  
  190.  
  191.  
  192.  
  193. [LISTING FOUR]
  194.  
  195. /* [Excerpted from /sys/i386/i386/machdep.c] */
  196.  
  197.   ...
  198. /* Fill out a gate descriptor uses as an interrupt vector. */
  199. setidt(idx, func, typ, dpl) char *func; {
  200.     struct gate_descriptor *ip = idt + idx;
  201.     ip->gd_looffset = (int)func;
  202.     ip->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
  203.     ip->gd_stkcpy = 0;
  204.     ip->gd_xx = 0;
  205.     ip->gd_type = typ;
  206.     ip->gd_dpl = dpl;   /* can we allow INT's to this IDT index? */
  207.     ip->gd_p = 1;       /* yup, we're here, don't segment fault me */
  208.     ip->gd_hioffset = ((int)func)>>16 ;
  209. }
  210.   ...
  211.  
  212.  
  213.  
  214.  
  215. [LISTING FIVE]
  216.  
  217. /* [Excerpted from /sys/i386/include/segments.h] */
  218.  
  219.   ...
  220. /* Gate descriptors (e.g. indirect descriptors)
  221.  * [The IDT is made up of these as well.] */
  222. struct  gate_descriptor {
  223.     unsigned gd_looffset:16 ;   /* gate offset (lsb) */
  224.     unsigned gd_selector:16 ;   /* gate segment selector */
  225.     unsigned gd_stkcpy:5 ;      /* number of stack wds to cpy */
  226.     unsigned gd_xx:3 ;      /* unused */
  227.     unsigned gd_type:5 ;        /* segment type */
  228.     unsigned gd_dpl:2 ;     /* segment descriptor priority level */
  229.     unsigned gd_p:1 ;       /* segment descriptor present */
  230.     unsigned gd_hioffset:16 ;   /* gate offset (msb) */
  231. } ;
  232.  ...
  233.  
  234.  
  235.  
  236.  
  237.